package com.ksl.kinglockguard.network.appupdate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.widget.Toast;

import com.ksl.kinglockguard.R;
import com.ksl.kinglockguard.data.Constants;
import com.ksl.kinglockguard.network.NetworkTask;
import com.ksl.kinglockguard.utils.KingsExecuteRoot;
import com.ksl.kinglockguard.utils.KingsSystemUtils;
import com.lsk.open.core.MyLog;
import com.lsk.open.core.net.NetConnectTask;
import com.lsk.open.core.net.NetHeadUtils;

public class AppUpdateService extends Service {

		private int fileSize; // 文件大小
		private int readSize = -1; // 读取长度
		private int downSize; // 已下载大小
		private File downFile; // 下载的文件

		@Override
		public IBinder onBind(Intent arg0) {
			return null;
		}

		@Override
		public void onCreate() {
			MyLog.i("ydy", "KingsreviveService onCreate");
			super.onCreate();
		}

		@Override
		public int onStartCommand(Intent intent, int flags, int startId) {
			
			if (intent != null) {
				boolean checkupdate = intent.getBooleanExtra("check_update",false);
//MyLog.i("ydy","KingsreviveService onStartCommand ---------- checkupdate: " + checkupdate);
				if(checkupdate){
					NetConnectTask networkTask = NetworkTask.requestUpdateMyApp(getApplicationContext());
					networkTask.setListener(new UpdateAppTaskListener(AppUpdateService.this, UpdateAppTaskListener.NOTIFY_TYPE_NOTIFICATION, null));
				}
				
				MyLog.i("ydy","KingsreviveService onStartCommand ---------- intent: " + intent);
				String downloadUrl = intent.getStringExtra("url");
				String type = intent.getStringExtra("type");
				boolean installNow = intent.getBooleanExtra("installNow", false);
				if(type != null && type.equals(Constants.APK_TYPE) && installNow){		//如果用户点击"立即安装"通知栏, 则立即开始安装.
					startInstall(downFile);
					downloadUrl = "";		//防止重新下载
				}
				
				if (downloadUrl != null && !downloadUrl.equals("")) {
					/**
					 *  1. 如果DownloadType是"静默下载", 则:downloadNow为true, showDownloadingNotification为false， 即: 立即下载,不显示通知栏
					 *  2. 如果DownloadType是"普通下载", 则:downloadNow为false, showDownloadingNotification为true, 即: 先不下载, 先显示提示有更新通知栏
					 *  3. 当用户点击"点击更新"的通知栏提示后, downloadNow为true, showDownloadingNotification为true, 即立即开始下载, 显示下载进度的通知栏
					 */
					long fileLength = intent.getLongExtra("fileLength",0);
					if (type != null && type.equals(Constants.APK_TYPE)) {
						boolean downloadNow = intent.getBooleanExtra(
								"downloadNow", false);
						boolean showDownloadingNotification = intent
								.getBooleanExtra("showDownloadingNotification",
										false);
						boolean showInstallNotification = intent.getBooleanExtra(
								"showInstallNotification", false);
						
						if (downloadNow) {
							startDownload(downloadUrl, type,
									showDownloadingNotification,showInstallNotification,fileLength);
						} else {
							showDownloadNotification(downloadUrl,
									showDownloadingNotification,fileLength);
						}
					} else {
						startDownload(downloadUrl, type, false, false,fileLength);
					}
				}
			}
			return super.onStartCommand(intent, flags, startId);
		}

		@Override
		public void onDestroy() {
			MyLog.i("ydy", "KingsreviveService onDestroy");
			super.onDestroy();
		}

		private boolean checkDownloadFileExists(String type, boolean showInstallNotification, long fileLength){
			
			String apkPath = AppUpdateFileUtil.getUpdateApkFilePath();
			File apkFile = new File(apkPath);
			
			
			MyLog.i("ydy", "checkDownloadFileExists ***** apkFile.exists: " + apkFile.exists());
			if(! apkFile.exists()){
				return false;
			}
			
			long length = apkFile.length();
			MyLog.i("ydy", "checkDownloadFileExists *****dowload fileLength==" + fileLength + " ;;length: " + length);
			if(length == fileLength){
				if(showInstallNotification){
					// 如果没有root, 则显示通知栏,供用户手动安装.
					showInstallNotification(apkFile.getAbsolutePath());
				} else {
					startInstall(apkFile);
				}
				return true;
			}else {
				apkFile.delete();
			}
			return false;
		}
		
		public static boolean isDownloadingUpdateApk = false;
		/**
		 * 下载模块
		 * 
		 * @param showDownloadingNotification
		 */
		private synchronized void startDownload(final String dowUrl,
				final String type, final boolean showDownloadingNotification, final boolean showInstallNotification,long fileLength) {
			
			boolean isNetWorking = NetHeadUtils.isNetWorking(getApplicationContext());
			if( !isNetWorking ){	//网络不好使
				Toast.makeText(getApplicationContext(), getString(R.string.lock_network_error_no_net_tip), Toast.LENGTH_SHORT).show();
				MyLog.i("jyh", "~~~~~~~//网络不好使~~~~~~~~~");
				return;
			}
			
			if(checkDownloadFileExists(type,showInstallNotification,fileLength)){
				return;
			}
			
			new Thread(new Runnable() {

				@Override
				public void run() {
					// 初始化数据
					fileSize = 0;
					readSize = 0;
					downSize = 0;

					isDownloadingUpdateApk = true;
					
					InputStream is = null;
					FileOutputStream fos = null;

					try {
						URL myURL = new URL(dowUrl); // 取得URL
						URLConnection conn = myURL.openConnection(); // 建立联机
						conn.connect();
						fileSize = conn.getContentLength(); // 获取文件长度
						String apkFilename = type;
						// 建立临时文件
						if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
							String downloadDir = AppUpdateFileUtil.getUpdateApkFilePathAndMakeDir();
							downFile = new File(downloadDir);

						} else {
							downFile = new File(getFilesDir() + File.separator + apkFilename);
						}
MyLog.i("ydy", "startDownload ----------- downFile.getAbsolutePath: " + downFile.getAbsolutePath());
						is = conn.getInputStream(); // InputStream 下载文件
						if (downFile.exists()) {
							downFile.delete();
							downFile.createNewFile();
						}
						// 将文件写入临时盘
						fos = new FileOutputStream(downFile);
						byte buf[] = new byte[1024 * 1024];
						while ((readSize = is.read(buf)) != -1) {
							fos.write(buf, 0, readSize);
							downSize += readSize;
							if (showDownloadingNotification) {
								updateDownloadNotificaton(fileSize, downSize);
							}
						}

						isDownloadingUpdateApk = false;
						
						if (type.equals(Constants.APK_TYPE)) {
							if(showInstallNotification){
								// 如果没有root, 则显示通知栏,供用户手动安装.
								showInstallNotification(downFile.getAbsolutePath());
							} else {
								startInstall(downFile);
							}
						}
						stopSelf();
					} catch (Exception e) {
						MyLog.i("ydy", "startDownload----Exception: " + e.getMessage());
						showDownloadFailedNotification(dowUrl);
						e.printStackTrace();
					} finally {
						isDownloadingUpdateApk = false;
						MyLog.i("ydy", "-------------finally --------------");
						try {
							if (null != fos)
								fos.close();
							if (null != is)
								is.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}

			}).start();
		}
		private void showDownloadFailedNotification(String url){
			String apkPath = AppUpdateFileUtil.getUpdateApkFilePath();
			File apk = new File(apkPath);
			MyLog.i("lijc", "showDownloadFailedNotification------------apkPath: " + apkPath);
			if (apk != null && apk.exists()) {
				apk.delete();
			}
			NotificationManager notificationManager = (NotificationManager) this
					.getSystemService(android.content.Context.NOTIFICATION_SERVICE);

			Notification notification = new Notification(
					R.drawable.lock_notify_icon, getString(R.string.lock_app_name),
					System.currentTimeMillis());
			notification.flags |= Notification.FLAG_AUTO_CANCEL;
			notification.ledARGB = Color.BLUE;

			// 设置通知的事件消息
			CharSequence contentTitle = getString(R.string.lock_app_name); // 通知栏标题
			CharSequence contentText = getString(R.string.failed_to_download_try_again) ; // 通知栏内容

			Intent reviveService = new Intent(getApplicationContext(),
					AppUpdateService.class);
			reviveService.putExtra("url", url);
			reviveService.putExtra("type", Constants.APK_TYPE);
			reviveService.putExtra("downloadNow", true);
			reviveService.putExtra("showDownloadingNotification", true);
			reviveService.putExtra("showDownloadedNotification", false);

			PendingIntent contentItent = PendingIntent.getService(
					getApplicationContext(), 0, reviveService, 0);
			
			notification.setLatestEventInfo(this, contentTitle, contentText,
					contentItent);
			

			// 把Notification传递给NotificationManager
			notificationManager.notify(NOTIFICATION_ID_DOWNLOADING,
					notification);
		}

		private void saveVersionCode(){
			String vcodeFile = AppUpdateFileUtil.getUpdateVersionPathAndMakeDir();
			File file = new File( vcodeFile );
			MyLog.i("version", "saveVersionCode-------------file.getAbsolutePath: " + file.getAbsolutePath());
			if (file.exists())
				file.delete();
			try {
				file.createNewFile();
				FileOutputStream fos = new FileOutputStream(file, true);
				
				PackageInfo packageInfo = getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
            	int versionCode = packageInfo.versionCode;
            	MyLog.i("version", "saveVersionCode-------------versionCode: " + versionCode);
            	
            	StringBuilder sb = new StringBuilder();
            	sb.append(versionCode);
				fos.write(sb.toString().getBytes());
				fos.close();
			} catch (Exception e) {
				MyLog.i("version", "saveVersionCode-------------Exception: " + e.getMessage());
				e.printStackTrace();
			}
		}
		
		protected void startInstall(File installPackage) {
			File apkFile = installPackage;
			
			if(installPackage == null  || "".equals(installPackage.getAbsolutePath())){
				apkFile = new File(AppUpdateFileUtil.getUpdateApkFilePath());
				if( apkFile == null || !apkFile.exists()){
					Toast.makeText(getApplicationContext(), "安装包不存在或也破损", Toast.LENGTH_SHORT).show();
					return;
				}
			}
			MyLog.i("update", "startInstall-------------apkFile.getAbsolutePath: " + apkFile.getAbsolutePath());
			
			boolean isRooted = hasRootAccess(getApplicationContext(), false);
			MyLog.i("update", "-------------isRooted: " + isRooted);
			if (isRooted) { // 如果已经root,则自动安装
				saveVersionCode();
				AppUpdateFileUtil.refreshApkToRootUpdate(apkFile.getAbsolutePath());
				apkFile.delete();
			} else { // 如果没有root, 则调出系统安装对话框,供用户手动安装.
				
				Intent intent = new Intent(Intent.ACTION_VIEW);
				intent.setDataAndType(Uri.fromFile(apkFile),
						"application/vnd.android.package-archive");
				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				startActivity(intent);
			}
			NotificationManager notificationManager = (NotificationManager) this
					.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
			notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING);		//下载进度的通知
			
			notificationManager.cancel(NOTIFICATION_ID_READY_TO_INSTALL);			//"点击安装"的通知
		}

		
		/**
		 * 在状态栏显示通知, 用户点击后开始下载
		 */
		private static final int NOTIFICATION_ID_READY_TO_DOWNLOAD = 12301;

		private void showDownloadNotification(String url,
				boolean showDownloadingNotification, long fileLength) {
			// 创建一个NotificationManager的引用
			NotificationManager notificationManager = (NotificationManager) this
					.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
			
			/* ------- 清除点击安装的对话框 ----------- */
			notificationManager.cancel(NOTIFICATION_ID_READY_TO_INSTALL);			//"点击安装"的通知
			
			
			// 定义Notification的各种属性
			Notification notification = new Notification(
					R.drawable.lock_notify_icon, getString(R.string.lock_app_name),
					System.currentTimeMillis());
			notification.flags |= Notification.FLAG_AUTO_CANCEL; // 表明在点击了通知栏中的"清除通知"后，此通知不清除，经常与FLAG_ONGOING_EVENT一起使用
			notification.defaults = Notification.DEFAULT_ALL;
			notification.ledARGB = Color.BLUE;

			// 设置通知的事件消息
			CharSequence contentTitle = getString(R.string.lock_app_name); // 通知栏标题
			CharSequence contentText = getString(R.string.lock_update_notification_ready_to_download); // 通知栏内容

			Intent reviveService = new Intent(getApplicationContext(),
					AppUpdateService.class);
			reviveService.putExtra("url", url);
			reviveService.putExtra("type", Constants.APK_TYPE);
			reviveService.putExtra("downloadNow", true);
			reviveService.putExtra("showDownloadingNotification", true);
			reviveService.putExtra("showDownloadedNotification", false);
			reviveService.putExtra("fileLength",fileLength);

			PendingIntent contentItent = PendingIntent.getService(
					getApplicationContext(), 0, reviveService, 0);
			notification.setLatestEventInfo(this, contentTitle, contentText,
					contentItent);

			// 把Notification传递给NotificationManager
			notificationManager.notify(NOTIFICATION_ID_READY_TO_DOWNLOAD, notification);
		}

		/**
		 * 在状态栏显示通知, 更新下载进度
		 */
		private static final int NOTIFICATION_ID_DOWNLOADING = 12302;

		protected void updateDownloadNotificaton(int readSize, int downSize) {
			NotificationManager notificationManager = (NotificationManager) this
					.getSystemService(android.content.Context.NOTIFICATION_SERVICE);

			Notification notification = new Notification(
					R.drawable.lock_notify_icon, getString(R.string.lock_app_name),
					System.currentTimeMillis());
			notification.flags |= Notification.FLAG_AUTO_CANCEL;
			notification.ledARGB = Color.BLUE;

			// 设置通知的事件消息
			CharSequence contentTitle = getString(R.string.lock_app_name); // 通知栏标题
			CharSequence contentText = "总大小:　" + KingsSystemUtils.dataFormat(readSize) + "      已下载:　" + KingsSystemUtils.dataFormat(downSize) ; // 通知栏内容
//			CharSequence contentText = "总大小:　" + readSize + "      已下载:　" + downSize ; // 通知栏内容
			
			notification.setLatestEventInfo(this, contentTitle, contentText,
					null);

			// 把Notification传递给NotificationManager
			notificationManager.notify(NOTIFICATION_ID_DOWNLOADING,
					notification);
		}

		/**
		 * 在状态栏显示通知, 用户点击后安装
		 */
		private static final int NOTIFICATION_ID_READY_TO_INSTALL = 12303;

		private void showInstallNotification(String absolutePath) {
			NotificationManager notificationManager = (NotificationManager) this
					.getSystemService(android.content.Context.NOTIFICATION_SERVICE);

			/* ------- 清除"点击下载"的对话框 ----------- */
			notificationManager.cancel(NOTIFICATION_ID_READY_TO_DOWNLOAD);			//"点击安装"的通知
			
			Notification notification = new Notification(
					R.drawable.lock_notify_icon, getString(R.string.lock_app_name),
					System.currentTimeMillis());
			notification.flags |= Notification.FLAG_AUTO_CANCEL; // 表明在点击了通知栏中的"清除通知"后，此通知不清除，经常与FLAG_ONGOING_EVENT一起使用
			notification.defaults = Notification.DEFAULT_ALL;
			// 设置通知的事件消息
			CharSequence contentTitle = getString(R.string.lock_app_name); // 通知栏标题
			CharSequence contentText = getString(R.string.lock_update_notification_ready_to_install); // 通知栏内容

			Intent reviveService = new Intent(this, AppUpdateService.class);
			reviveService.putExtra("type", Constants.APK_TYPE);
			reviveService.putExtra("installNow", true);	//立即开始安装.

			PendingIntent contentItent = PendingIntent.getService(this, 0,
					reviveService, 0);
			notification.setLatestEventInfo(this, contentTitle, contentText,
					contentItent);

			notificationManager.notify(NOTIFICATION_ID_READY_TO_INSTALL, notification);
		}
		
		/**
		 * 判断是否有root权限，没有root权限显示dialog对话框
		 */
		public static boolean hasRootAccess(Context ctx, boolean showErrors) {
			// if (hasroot)
			// return true;
			final StringBuilder res = new StringBuilder();
			try {
				// Run an empty script just to check root access
				if (runScriptAsRoot(ctx, "echo test", res) == 0) {
					// hasroot = true;
					return true;
				}
			} catch (Exception e) {

			}

			return false;
		}

		/**
		 * 运行一个root权限的脚本
		 */
		public static int runScriptAsRoot(Context ctx, String script,
				StringBuilder res, long timeout) {
			return runScript(ctx, script, res, timeout, true);
		}

		/**
		 * 运行一个root权限的脚本
		 */
		public static int runScriptAsRoot(Context ctx, String script,
				StringBuilder res) throws IOException {
			return runScriptAsRoot(ctx, script, res, 40000);
		}

		/** root script filename */
		private static final String SCRIPT_FILE = "droidwall.sh";

		public static int runScript(Context ctx, String script,
				StringBuilder res, long timeout, boolean asroot) {
			final File file = new File(ctx.getDir("bin", 0), SCRIPT_FILE);
			final ScriptRunner runner = new ScriptRunner(file, script, res,
					asroot);
			runner.start();
			try {
				if (timeout > 0) {
					runner.join(timeout);
				} else {
					runner.join();
				}
				if (runner.isAlive()) {
					// Timed-out
					runner.interrupt();
					runner.join(150);
					runner.destroy();
					runner.join(50);
				}
			} catch (InterruptedException ex) {
			}
			return runner.exitcode;
		}

		/**
		 * 启用新线程来运行脚本
		 */
		private static final class ScriptRunner extends Thread {
			private final File file;
			private final String script;
			private final StringBuilder res;
			private final boolean asroot;
			public int exitcode = -1;

			// private static Process exec;

			public ScriptRunner(File file, String script, StringBuilder res,
					boolean asroot) {
				this.file = file;
				this.script = script;
				this.res = res;
				this.asroot = asroot;
			}

			@Override
			public void run() {
				try {
					file.createNewFile();
					final String abspath = file.getAbsolutePath();
					if ((Build.VERSION.SDK_INT >= 9 && !file.canExecute())
							|| !file.canRead() || !file.canWrite()) {
						// make sure we have execution permission on the script
						// file
						Runtime.getRuntime().exec("chmod 777 " + abspath)
								.waitFor();
						// Write the script to be executed
					}

					final OutputStreamWriter out = new OutputStreamWriter(
							new FileOutputStream(file));
					if (new File("/system/bin/sh").exists()) {
						out.write("#!/system/bin/sh\n");
					}
					out.write("myfunction(){\n");
					out.write(script);
					if (!script.endsWith("\n"))
						out.write("\n");
					out.write("}\n");
					out.write("myfunction\n");
					out.write("echo myfunction return=$?");
					// out.write("exit\n");
					out.flush();
					out.close();

					MyLog.e("gaojing", script);
//TODO Lijc
					KingsExecuteRoot root = KingsExecuteRoot
							.getExecuteRoot(this.asroot);
					String result = root.runCommand("sh " + abspath);

//					String result = "";
					if (result != null) {
						String[] rets = result.split("\n");
						if (rets != null) {
							String exit = rets[rets.length - 1];
							if (exit.startsWith("myfunction return=")) {
								exit = exit.substring(
										"myfunction return=".length(),
										exit.length());
							}
							this.exitcode = Integer.parseInt(exit);
						}
					}

					MyLog.e("gaojing", "firewall result= " + result);
				} catch (InterruptedException ex) {
					if (res != null)
						res.append("\nOperation timed-out");
				} catch (Exception ex) {
					if (res != null)
						res.append("\n" + ex);
				} finally {
					destroy();
				}
			}

			/**
			 * Destroy this script runner
			 */
			public synchronized void destroy() {
				// if (exec != null)
				// exec.destroy();
				// exec = null;
			}
		}

}